#include <Precomp.h>

#include "DebugHelper.h"

#if DEBUG

vector<CDebugHelper::CDebugLine*> CDebugHelper::ms_lineList;
vector<CDebugHelper::CDebugPoint*> CDebugHelper::ms_pointList;
Ogre::SceneManager* CDebugHelper::ms_pSceneManager;

void CDebugHelper::InitializeForScene(Ogre::SceneManager* pSceneManager)
{
    ms_pSceneManager = pSceneManager;
}

void CDebugHelper::DrawPoint(Ogre::Vector3 vectorPoint, float flScale, int cFrames, const Ogre::ColourValue& color)
{
    int index = -1;

    for(unsigned int i = 0; i < ms_pointList.size(); i++)
    {
        if(ms_pointList[i]->GetFramesLeft() == 0)
        {
            index = i;
            break;
        }
    }

    if(index == -1)
    {
        ms_pointList.push_back(new CDebugPoint(ms_pSceneManager));
        index = ms_pointList.size() - 1;
    }

    ms_pointList[index]->TrackPoint(vectorPoint, flScale, cFrames, color);

}



void CDebugHelper::DrawLine(Ogre::Vector3 vectorFrom, Ogre::Vector3 vectorTo, float flScale, int cFrames, const Ogre::ColourValue& color)
{
    int index = -1;

    for(unsigned int i = 0; i < ms_pointList.size(); i++)
    {
        if(ms_lineList[i]->GetFramesLeft() == 0)
        {
            index = i;
            break;
        }
    }

    if(index == -1)
    {
        ms_lineList.push_back(new CDebugLine(ms_pSceneManager));
        index = ms_lineList.size() - 1;
    }

    ms_lineList[index]->TrackLine(vectorFrom, vectorTo, flScale, cFrames, color);
}


void CDebugHelper::Update()
{
    for(unsigned int i = 0; i < ms_pointList.size(); i++)
    {
        ms_pointList[i]->Update();
    }

    for(unsigned int i = 0; i < ms_lineList.size(); i++)
    {
        ms_lineList[i]->Update();
    }
}



int CDebugHelper::CDebugPoint::m_sSerialNumber = 0;

CDebugHelper::CDebugPoint::CDebugPoint(Ogre::SceneManager* pSceneManager) : m_cFramesLeft(0)
{
    ostringstream pointNameStream;

    pointNameStream << "Point" << m_sSerialNumber++;

    string pointName = pointNameStream.str();

    m_pBillboardSet = pSceneManager->createBillboardSet(pointName, 1);
    m_pBillboardSet->setMaterialName("debugPlusMaterial");
    m_pBillboardSet->setDefaultDimensions(1.0f, 1.0f);

    m_pBillboard = m_pBillboardSet->createBillboard(0.0f, 0.0f, 0.0f);

    m_pNode = pSceneManager->createSceneNode(pointName);
    m_pNode->attachObject(m_pBillboardSet);

}

CDebugHelper::CDebugPoint::~CDebugPoint()
{
    if(m_pBillboard != NULL)
    {
        m_pBillboardSet->removeBillboard(m_pBillboard);
        m_pBillboard = NULL;
    }

    if(m_pBillboardSet != NULL)
    {
        m_pNode->detachObject(m_pBillboardSet);
        m_pNode->getCreator()->destroyBillboardSet(m_pBillboardSet);
        m_pBillboardSet = NULL;
    }

    if(m_pNode != NULL)
    {
        if(m_pNode->getParentSceneNode() != NULL)
        {
            m_pNode->getParentSceneNode()->removeChild(m_pNode);

        }
        m_pNode->getCreator()->destroySceneNode(m_pNode->getName());
        m_pNode = NULL;
    }
}

void CDebugHelper::CDebugPoint::TrackPoint(Ogre::Vector3 vectorPoint, float flScale, int cFrames, const Ogre::ColourValue& color)
{
    m_pBillboard->setColour(color);
    m_pNode->getCreator()->getRootSceneNode()->addChild(m_pNode);
    m_pNode->setScale(flScale, flScale, flScale);
    m_pNode->setPosition(vectorPoint.x, vectorPoint.y, vectorPoint.z);
    m_cFramesLeft = cFrames;
}

void CDebugHelper::CDebugPoint::Update()
{
    if(m_cFramesLeft <= 0)
    {
        return;
    }

    m_cFramesLeft -= 1;

    if(m_cFramesLeft == 0)
    {
        m_pNode->getCreator()->getRootSceneNode()->removeChild(m_pNode);
    }
}



int CDebugHelper::CDebugLine::m_sSerialNumber = 0;

CDebugHelper::CDebugLine::CDebugLine(Ogre::SceneManager* pSceneManager) : m_cFramesLeft(0)
{
    ostringstream pointNameStream;

    pointNameStream << "Line" << m_sSerialNumber++;

    string pointName = pointNameStream.str();

    m_pBillboardSet = pSceneManager->createBillboardSet(pointName, 1);
    m_pBillboardSet->setMaterialName("debugArrowMaterial");
    m_pBillboardSet->setDefaultDimensions(1.0f, 1.0f);
    m_pBillboardSet->setBillboardType(Ogre::BBT_ORIENTED_SELF);

    m_pBillboard = m_pBillboardSet->createBillboard(0.0f, 0.0f, 0.0f);

    m_pNode = pSceneManager->createSceneNode(pointName);
    m_pNode->attachObject(m_pBillboardSet);

}

CDebugHelper::CDebugLine::~CDebugLine()
{
    if(m_pBillboard != NULL)
    {
        m_pBillboardSet->removeBillboard(m_pBillboard);
        m_pBillboard = NULL;
    }

    if(m_pBillboardSet != NULL)
    {
        m_pNode->detachObject(m_pBillboardSet);
        m_pNode->getCreator()->destroyBillboardSet(m_pBillboardSet);
        m_pBillboardSet = NULL;
    }

    if(m_pNode != NULL)
    {
        if(m_pNode->getParentSceneNode() != NULL)
        {
            m_pNode->getParentSceneNode()->removeChild(m_pNode);

        }
        m_pNode->getCreator()->destroySceneNode(m_pNode->getName());
        m_pNode = NULL;
    }
}

void CDebugHelper::CDebugLine::TrackLine(Ogre::Vector3 vectorFrom, Ogre::Vector3 vectorTo, float flScale, int cFrames, const Ogre::ColourValue& color)
{
    m_pNode->getCreator()->getRootSceneNode()->addChild(m_pNode);
    m_cFramesLeft = cFrames;

    Ogre::Vector3 vectorResult = vectorTo - vectorFrom;

    float flLength = vectorResult.length();
    vectorResult.normalise();

    m_pBillboard->setDimensions(flScale, flLength);
    m_pBillboard->mDirection = vectorResult;
    m_pBillboard->setColour(color);

    Ogre::Vector3 vectorOffset = (vectorResult * flLength / 2.0f) + vectorFrom;
    m_pNode->setPosition(vectorOffset.x, vectorOffset.y, vectorOffset.z);
}

void CDebugHelper::CDebugLine::Update()
{
    if(m_cFramesLeft <= 0)
    {
        return;
    }

    m_cFramesLeft -= 1;

    if(m_cFramesLeft == 0)
    {
        m_pNode->getCreator()->getRootSceneNode()->removeChild(m_pNode);
    }
}

void CDebugHelper::PrintDebugString(const char* szFmt, ...)
{
    char szBuf[2048];
    va_list va;
    va_start(va, szFmt);

    vsnprintf_s(szBuf, sizeof(szBuf) - 1, _TRUNCATE, szFmt, va);
    szBuf[sizeof(szBuf) - 1] = '\0';
    OutputDebugString(szBuf);
}



#endif
